package model.invoicing;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;


/**
 * Utility class for handling <code>Date</code>.
 * 
 * @author Matthias Haupt
 *
 */
public final class DateHandler {
	private final static Logger log = LogManager.getLogger("ERROR");	
	
	public enum InvoiceDate {
		FIRSTDAY, LASTDAY;
	}
	
	private DateHandler(){
		throw new AssertionError("Utility class musn't be invoked!");
	}
	
	/**
	 * Gets the First or last day of a given Date, depending on the parameter day
	 * @param date
	 * @param day
	 * @return date
	 */
	public static Date getDayFromDate(Date date, InvoiceDate day){

		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		Date ret = null;
	
		if (day.equals(DateHandler.InvoiceDate.FIRSTDAY)) {
			calendar.set(Calendar.DAY_OF_MONTH, 1);
			ret = calendar.getTime();
		} else if (day.equals(DateHandler.InvoiceDate.LASTDAY)) {
			calendar.add(Calendar.MONTH, 1);  
	        calendar.set(Calendar.DAY_OF_MONTH, 1);  
	        calendar.add(Calendar.DATE, -1);  
	
			ret = calendar.getTime();
		}
		return ret;
	}
	
	/**
	 * Gets the month of a given date.
	 * e.g.: For a date 01-03-2014 it returns Maerz.
	 * @param date
	 * @return String representation of the month of the given date.
	 */
	public static String getMonthFromDate(Date date){
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.GERMANY);
	}
	
	/**
	 * Returns the Date when a Bill needs to be paid.
	 * @return
	 */
	public static Date getPayDate(){
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
		return cal.getTime();
	}

	/**
	 * Gets the date object representing the month before the given date.
	 * @param today
	 * @return
	 */
	public static Date getMonthBeforeDate(Date today) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(today);
		cal.add(Calendar.MONTH, -1);
		return cal.getTime();
	}
	
	/**
	 * Returns the String representation of a given date.
	 * e.g. for 01-03-2014 it returns 01. Maerz 2014
	 * @param date
	 * @return
	 */
	public static String formatDayDateToString(Date date){
		DateFormat sdf = new SimpleDateFormat("dd. MMMMMMMMM yyyy", Locale.GERMANY);
		return sdf.format(date);
	}
	
	/**
	 * Returns the short String representation of a given date.
	 * e.g.: for 01-03-2014 it returns 01.03.2014
	 * @param date
	 * @return
	 */
	public static String formatShortDayDateToString(Date date){
		DateFormat sdf = new SimpleDateFormat("dd.MM.yyyy", Locale.GERMANY);
		return sdf.format(date);
	}
	
	/**
	 * Returns month String representation of a given date.
	 * e.g. for 01-03-2014 it returns 2014-03
	 * @param date
	 * @return
	 */
	public static String formatMonthDateToString(Date date){
		DateFormat sdf = new SimpleDateFormat("yyyy-MM");
		return sdf.format(date);
	}

	/**
	 * Formats a given date to a string representation.
	 * e.g. for 01-03-2014 it returns Maerz 2014
	 * @param date
	 * @return
	 */
	public static String formatHeaderDate(Date date) {
		String invoicePeriod;
		invoicePeriod = new SimpleDateFormat("MMMMMMMMMMMMMM yyyy", Locale.GERMANY).format(date);
		return invoicePeriod;
	}
	
	/**
	 * Returns the normal String representation of given date.
	 * e.g. the return value is 2014-03-01
	 * @param date
	 * @return
	 */
	public static String formatNormalDate(Date date){
		String normalDate = new SimpleDateFormat("yyyy-MM-dd").format(date);
		return normalDate;
	}
	
	/**
	 * Parses string containing a date with the format yyyy-MM-dd to a Date object
	 * @param dateString
	 * @return Date object of the string representation or null if an error occurred
	 */
	public static Date parseNormalDateStringToDate(String dateString){
		Date res = null;
		try {
			res = new SimpleDateFormat("yyyy-MM-dd").parse(dateString);
		} catch (ParseException e) {
			
			e.printStackTrace();
		}
		return res;
	}
	
	/**
	 * Parses the given String representation of the date (format: yyyy-MM) to a Date object
	 * @param monthDateString
	 * @return Date object of the given String representation or null if an error occurred
	 */
	public static Date parseMonthDateStringToDate(String monthDateString){
		Date date = null;
		try {
			date = new SimpleDateFormat("yyyy-MM").parse(monthDateString);
		} catch (ParseException e) {
			log.error(e.getMessage());
			e.printStackTrace();
		}
		return date;
	}

	/**
	 * Returns the Index of a given month.
	 * e.g.: For a given value = "Januar" , 01 is returned
	 * @param value
	 * @return
	 */
	public static String formatStringMonthToNumber(String value) {
		  String months[] = {"Januar", "Februar", "März", "April",
                  "Mai", "Juni", "Juli", "August", "September",
                  "Oktober", "November", "Dezember"};
		  
		  for(int i = 0; i<12 ; i++){
			  if(months[i].equals(value)){
				  if(i<9){
					  int temp = i;
					  temp = temp+1;
					  return "0" +temp;
				  } else{
					  int temp = i;
					  temp = temp+1;
					  return String.valueOf(temp);
				  }
			  }
		  }
		throw new IllegalArgumentException("Wrong input value");
	}
}
